
package stcu;

import stcu.robjects.*;
import com.nvlled.route.*;
import java.net.*;
import java.util.*;

public class Prober implements 
        Runnable,
        ObjectReceiver<ProbeResponse> {

    public static final String SERVER_PREFIX = "server-";
    public static final long MIN_WAIT_TIME = 2000;
    public static final long UPPER_WAIT_TIME = 5000;
    public static final long MAX_WAIT_TIME = UPPER_WAIT_TIME + MIN_WAIT_TIME;

    private boolean probing = false;
    private ObjectRouter router; 
    private AddressTable addressTable;

    private Listener listener;

    public Prober(ObjectRouter router) {
        this.router = router;
        addressTable = router.getTable();

        router.subscribe(ProbeResponse.class, this);
        listener = new Deaf();
    }

    public void stop() {
        probing = false;
    }

    public void setListener(Listener listener) {
        if (listener != null) {
            this.listener = listener;
        }
    }

    public void probe() {
        probing = true;
        while (probing) {
            sendProbe();
            randomWait();
        }
    }

    public void sendProbe() {
        router.deliverBroadcast(new ServerProbe());
    }

    public void run() {
        probe();
    }

    public List<String> getServerNames() {
        List<String> names = new ArrayList<String>();
        AddressTable table = router.getTable();
        for(String name: table.getNames()) {
            if (name.startsWith(SERVER_PREFIX)) {
                names.add(name);
            }
        }
        return names;
    }

    public int getServerCount() {
        int count = 0;
        for (String id: addressTable.getNames()) {
            if (id.startsWith(SERVER_PREFIX)) {
                count++;
            }
        }
        return count;
    }

    private void randomWait() {
        try {
            Thread.sleep((long)(MIN_WAIT_TIME + 
                        Math.random() * UPPER_WAIT_TIME));
        } catch (Exception e) {  }
    }

    public void receive(ProbeResponse resp) {
        addressTable.store(SERVER_PREFIX+resp.getServerName(), resp.getSourceAddress());
        listener.serverFound(resp);
    }

    public interface Listener {
        public void serverFound(ProbeResponse server);
    }

    class Deaf implements Listener {
        public void serverFound(ProbeResponse server) { }
    }
}

